package com.client.service;

import com.alibaba.fastjson.JSON;
import com.client.entity.sm9.Key;
import com.client.sm9.gm.sm9.MasterPublicKey;
import com.client.sm9.gm.sm9.PrivateKey;
import com.client.sm9.gm.sm9.SM9Curve;
import lombok.Getter;
import lombok.SneakyThrows;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.web.client.RestTemplate;

import java.io.*;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

@Getter
@Service
public class KeyService {

    SM9Curve sm9Curve = new SM9Curve();

    //加密主公钥
    private final MasterPublicKey Ppub_e;
    //签名主公钥
    private final MasterPublicKey Ppub_s;
    //加密私钥
    private final PrivateKey de;
    //签名私钥
    private final PrivateKey ds;
    //密钥交换私钥
    private final PrivateKey d_exchange;
    //标识
    @Value("${id}")
    private final String id = null;

    public KeyService() {
        Ppub_e = readPpub_e();
        Ppub_s = readPpub_s();
        de = readde();
        ds = readds();
        d_exchange = readd_exchange();
    }

    private PrivateKey readd_exchange() {
        try {
            Key key = readKeyFormLocal();
            //读取密钥交换私钥
            byte[] bexchange = new BigInteger(key.getD_exchange().toString(), 16).toByteArray();
            bexchange = getbyte(bexchange);
            PrivateKey privateKey = PrivateKey.ExchangefromByteArray(sm9Curve, bexchange);
            privateKey.d.setFromBytes(bexchange);
            return privateKey;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    //读取本地密钥、标识转化为对象
    @SneakyThrows
    public Key readKeyFormLocal() throws FileNotFoundException {
        File jsonFile = ResourceUtils.getFile("src/main/resources/static/data.json");
        //将json转化为String
        String json = FileUtils.readFileToString(jsonFile);
        return JSON.parseObject(json, Key.class);
    }

    //向KGC发送http请求获取密钥
    public Key getKeyFormKGC(String id) {
        RestTemplate restTemplate = new RestTemplate();
        String url = "http://localhost:8088/getKeys";
        //①：请求体，发送的时候会被转换为json格式数据
        Map<String, String> body = new HashMap<>();
        body.put("ID", this.id);
        body.put("IP", "127.0.0.1");
        //②：头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
//        headers.add("header1", "v1");
//        headers.add("header2", "v2");

        //这里收包有些问题，可能是属性名的原因
        HttpEntity httpEntity = new HttpEntity(body, headers);

        Key key = restTemplate.postForObject(url, httpEntity, Key.class);

        return key;
    }

    //将密钥以JSON保存到本地
    public void saveKey(Key key) throws FileNotFoundException {
        try {
            FileWriter wf = new FileWriter("src/main/resources/static/data.json");
            String s = JSON.toJSONString(key);
            wf.write(s);
            wf.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //从本地读取加密主公钥
    private MasterPublicKey readPpub_e() {
        try {
            Key key = readKeyFormLocal();
            //加密主公钥
            byte[] Ppub_e = new BigInteger(key.getPpub_e(), 16).toByteArray();
            Ppub_e = getbyte(Ppub_e);
            MasterPublicKey masterPublicKey = MasterPublicKey.EncrytfromByteArray(sm9Curve, Ppub_e);
            masterPublicKey.Q.setFromBytes(Ppub_e);
            return masterPublicKey;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    //从本地读取签名主公钥
    private MasterPublicKey readPpub_s() {
        try {
            Key key = readKeyFormLocal();
            //读取签名主公钥

            byte[] Ppub_s = new BigInteger(key.getPpub_s().toString(), 16).toByteArray();
            Ppub_s = getbyte(Ppub_s);
            MasterPublicKey masterPublicKey = MasterPublicKey.SignfromByteArray(sm9Curve, Ppub_s);
            masterPublicKey.Q.setFromBytes(Ppub_s);
            return masterPublicKey;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    //从本地读取加密私钥
    private PrivateKey readde() {
        try {
            Key key = readKeyFormLocal();
            //读取加密私钥
            byte[] bde = new BigInteger(key.getDe().toString(), 16).toByteArray();
            bde = getbyte(bde);
            PrivateKey privateKey = PrivateKey.EncrytfromByteArray(sm9Curve, bde);
            privateKey.d.setFromBytes(bde);
            return privateKey;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    //从本地读取签名私钥
    private PrivateKey readds() {
        try {
            Key key = readKeyFormLocal();
            //读取用户签名私钥
            byte[] ds = new BigInteger(key.getDs(), 16).toByteArray();
            ds = getbyte(ds);
            PrivateKey privateKey = PrivateKey.SignfromByteArray(sm9Curve, ds);
            privateKey.d.setFromBytes(ds);
            return privateKey;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    //去除字节数组开头多余的0
    public byte[] getbyte(byte[] t) {
        if (t.length % 2 != 0) {
            byte[] bos = new byte[t.length - 1];
            System.arraycopy(t, 1, bos, 0, t.length - 1);
            return bos;
        } else {
            return t;
        }
    }

    public byte[] getbyte1(byte[] t) {
        if (t[0] == 0) {
            byte[] bos = new byte[t.length - 1];
            System.arraycopy(t, 1, bos, 0, t.length - 1);
            return bos;
        } else {
            return t;
        }
    }
}
